package com.ttl;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName TestTTL
 * @Description TODO
 * @Author admin
 * @Date 2021/6/3 15:15
 * @Version 1.0
 **/
public class TestTTL {
    
    // 需要注意的是，使用TTL的时候，要想传递的值不出问题，线程池必须得用TTL加一层代理（下面会讲这样做的目的）
    private static ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));
    
    private static ThreadLocal tl = new TransmittableThreadLocal<>(); //这里采用TTL的实现
    
    public static void main(String[] args) {
        
        tl.set(55);
        
        new Thread(() -> {
            
            String mainThreadName = "main_01";
            
            tl.set(1);
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(1), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(1), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(1), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            sleep(1L); //确保上面的会在tl.set执行之前执行
            tl.set(2); // 等上面的线程池第一次启用完了，父线程再给自己赋值
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(2), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(2), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(2), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            System.out.println(String.format("thread name-%s, variables=%s", Thread.currentThread().getName(), tl.get()));
            
        }).start();
        
        new Thread(() -> {
            
            String mainThreadName = "main_02";
            
            tl.set(3);
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(3), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(3), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("Before local variables are changed(3), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            sleep(1L); //确保上面的会在tl.set执行之前执行
            tl.set(4); // 等上面的线程池第一次启用完了，父线程再给自己赋值
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(4), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(4), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            executorService.execute(() -> {
                sleep(1L);
                System.out.println(String.format("After the local variable is changed(4), parent name-%s, child name-%s, variables=%s", mainThreadName, Thread.currentThread().getName(), tl.get()));
            });
            
            System.out.println(String.format("thread name-%s, variables=%s", Thread.currentThread().getName(), tl.get()));
            
        }).start();
    
        sleep(1000);
        new Thread(() -> {
           executorService.execute(()->{
               sleep(1L);
               System.out.println("-------------" + tl.get() + "-------------");
           });
        }).start();
        
    }
    
    private static void sleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
